package com.kemai.customize

import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import android.widget.OverScroller
import com.kemai.view.R

/**

 *@description:TODO
 * @author: zhaoshanshan
 * @date: 2022/11/29 9:36 下午

 */
class PhotoView :View {
    private lateinit var bitMap:Bitmap
    private lateinit var paint: Paint
    private  var originalOffsetX:Float = 0.0f
    private  var originalOffsetY:Float = 0.0f
    private  var smallScale:Float = 0.0f
    private  var bigScale:Float = 0.0f
    private  var scaleSize:Float = 1.5f
    private  var currentScaleSize:Float = 0.0f
    private var isEnLarge = false//是否是放大状态
    private lateinit var gestureDetector:GestureDetector
    private  var objectAnimator:ObjectAnimator? = null
    private var offsetX = 0.0f
    private var offsetY = 0.0f
    private lateinit var overScroller:OverScroller
    private lateinit var flingRunnable: FlingRunnable
    private lateinit var photoScaleGestureDetector:ScaleGestureDetector
    private var isScale = false
    constructor(context: Context):this(context,null){}
    constructor(context: Context, attrs: AttributeSet?):this(context,attrs,0){}
    constructor(context: Context, attrs: AttributeSet?, defaultStyle:Int) : super(context,attrs,defaultStyle) {
        init(context)
    }

    private fun init(context: Context) {
        bitMap = BitmapFactory.decodeResource(context.resources, R.mipmap.photo)
        paint = Paint()
        gestureDetector = GestureDetector(context,PhotoGestureListener())
        overScroller = OverScroller(context)
        flingRunnable = FlingRunnable()
        photoScaleGestureDetector = ScaleGestureDetector(context, PhotoScaleGestureDetector())
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        var result = photoScaleGestureDetector.onTouchEvent(event)
        if(!photoScaleGestureDetector.isInProgress){
            result = gestureDetector.onTouchEvent(event)
        }
        return result
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        //平移
        val scaleFraction = (currentScaleSize-smallScale)/(bigScale-smallScale)//缩小时候不平移 放大的时候 平移比例为1
        canvas?.translate(offsetX*scaleFraction,offsetY*scaleFraction)
        //缩放
        if(currentScaleSize<=smallScale){
            currentScaleSize = smallScale
        }
        canvas?.scale(currentScaleSize,currentScaleSize,width/2.0f,height/2.0f)
        //画图
        canvas?.drawBitmap(bitMap,originalOffsetX,originalOffsetY,paint)
    }
    //onMeasure方法之后 onDraw方法之前会进行调用 尺寸改变时间 也会进行调用
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        originalOffsetX = (width-bitMap.width)/2.0f
        originalOffsetY = (height-bitMap.height)/2.0f

        //判断图片是否是横向图片还是纵向图片
        if(bitMap.width/bitMap.height>width/height){//横向图片 图片宽高比大于屏幕宽高比
            smallScale = width.toFloat()/bitMap.width.toFloat()
            bigScale = (height.toFloat()/bitMap.height.toFloat())*scaleSize
        }else{//纵向图片
            smallScale = (height.toFloat()/bitMap.height.toFloat()).toFloat()
            bigScale = (width.toFloat()/bitMap.width.toFloat())*scaleSize
        }
        currentScaleSize = smallScale

    }
    //系统提供手势类SimpleOnGestureListener
    inner class PhotoGestureListener: SimpleOnGestureListener() {

        //按下 需要直接返回true 进行事件消费
        override fun onDown(e: MotionEvent?): Boolean {
            //return super.onDown(e)
            return true
        }
        //延时触发 100ms 点击水波纹效果
        override fun onShowPress(e: MotionEvent?) {
            super.onShowPress(e)
        }
        //单击抬起触发
        override fun onSingleTapUp(e: MotionEvent?): Boolean {
            return super.onSingleTapUp(e)
        }
        //类似move事件
        override fun onScroll(
            e1: MotionEvent?,
            e2: MotionEvent?,
            distanceX: Float,//distanceX 在X轴划过的距离,旧位置-新位置 值为负数
            distanceY: Float//distanceY 在Y轴划过的距离,旧位置-新位置 值为负数
        ): Boolean {
            if(currentScaleSize<=smallScale||isScale){
             return true
            }
            if(isEnLarge){//放大情况下进行平移
                offsetX -= distanceX
                offsetY -= distanceY
                fixOffsets()
                invalidate()

            }

            return super.onScroll(e1, e2, distanceX, distanceY)
        }
        //长按事件 300ms
        override fun onLongPress(e: MotionEvent?) {
            super.onLongPress(e)
        }
        //抛掷事件(惯性滑动事件)
        override fun onFling( e1: MotionEvent?, e2: MotionEvent?, velocityX: Float,velocityY: Float): Boolean {
            if(isEnLarge){//处理抛掷事件
                overScroller.fling(offsetX.toInt(),offsetY.toInt(),velocityX.toInt(),velocityY.toInt(),
                    -((bitMap.width*bigScale-width)/2).toInt(),((bitMap.width*bigScale-width)/2).toInt(),
                    -((bitMap.height*bigScale-height)/2).toInt(),((bitMap.height*bigScale-height)/2).toInt(),
                   300,300)
                postOnAnimation(flingRunnable)
            }

            return super.onFling(e1, e2, velocityX, velocityY)
        }
        //单击时触发，双击时不触发，延迟300ms的tap事件
        override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
            return super.onSingleTapConfirmed(e)
        }
        //双击抬起时触发
        override fun onDoubleTap(e: MotionEvent?): Boolean {
            isEnLarge = !isEnLarge
             if(isEnLarge){//放大
                currentScaleSize = bigScale
                offsetX = (e!!.x-width/2)-(e!!.x-width/2)*bigScale/smallScale
                offsetY = (e!!.y-height/2)-(e!!.y-height/2)*bigScale/smallScale
                fixOffsets()
                getObjectAnimator().start()
            }else{
                 currentScaleSize = smallScale
                 getObjectAnimator().reverse()
            }
            return super.onDoubleTap(e)
        }
        //双击第二次的down move up 时触发
        override fun onDoubleTapEvent(e: MotionEvent?): Boolean {
            return super.onDoubleTapEvent(e)
        }
    }

    private fun getObjectAnimator():ObjectAnimator{
        if(null==objectAnimator){
            objectAnimator = ObjectAnimator.ofFloat(this,"currentScaleSize",0.0f)
        }
        if(isScale){
            isScale = false
            objectAnimator?.setFloatValues(smallScale,currentScaleSize)
        }else{
            objectAnimator?.setFloatValues(smallScale,bigScale)
        }

        return objectAnimator!!
    }
    private fun setCurrentScaleSize(currentScaleSize:Float){
        if(currentScaleSize<=smallScale||isScale){
         return
        }
        this.currentScaleSize = currentScaleSize
        invalidate()


    }
    private fun fixOffsets(){
        offsetX = offsetX.coerceAtMost((bitMap.width * bigScale - width) / 2.0f)
        offsetX = offsetX.coerceAtLeast(-(bitMap.width * bigScale - width) / 2.0f)
        offsetY = offsetY.coerceAtMost((bitMap.height * bigScale - height) / 2.0f)
        offsetY = offsetY.coerceAtLeast(-(bitMap.height * bigScale - height) / 2.0f)


    }

    private inner class FlingRunnable:Runnable{
        override fun run() {
            if(overScroller.computeScrollOffset()){//动画正在执行
                offsetX = overScroller.currX.toFloat()
                offsetY = overScroller.currY.toFloat()
                Log.i("invalidate", "FlingRunnable")
                if(currentScaleSize>smallScale){
                    invalidate()
                }
                postOnAnimation(this)
            }
        }

    }

    private inner class PhotoScaleGestureDetector:ScaleGestureDetector.OnScaleGestureListener{
        private var initScale = 0.0f
        override fun onScale(detector: ScaleGestureDetector?): Boolean {

            if((currentScaleSize>smallScale&&!isEnLarge)||(currentScaleSize==smallScale&&isEnLarge)){
                isEnLarge = !isEnabled
            }
            currentScaleSize = initScale*detector!!.scaleFactor
            isScale = true
            if(initScale*detector!!.scaleFactor<=1.0f){
                if(currentScaleSize<=smallScale){
                    return false
                }
            }
            invalidate()
            return false

        }

        override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean {
            initScale = currentScaleSize;
            return true

        }

        override fun onScaleEnd(detector: ScaleGestureDetector?) {

        }


    }

}
